﻿/*****************************************************************************************************************************************************
 *   
 *   说明：
 *   
 *   完整报文的格式如下所示：
 *   数据格式类似: -234,263,-271\n
 *   ParkingOriginalPacket类:  对完整报文的解析，完成FCS校验，完成DATA数据的提取，提取出的DATA继续进行解析，然后通过Event机制交给相应的事件处理函数处理
 *                             ParkingOriginalPacket.EvProcessReceivedPacket += sp_EvProcessReceivedPacket; // sp_EvProcessReceivedPacket就是用户自己定义的事件处理函数
 *   时间：2015/12/17
 * 
 *   作者：zhaokang
 * 
 *****************************************************************************************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LRSystem;
using System.Threading;
using System.IO.Ports;
using System.Net.Sockets;

namespace LRSystem
{

    public static class MagneticOriginalPacket
    {
        static AutoResetEvent autoEvent = new AutoResetEvent(false); // 控制线程用的
        static Queue<baseReceivedPacket> pkqueue;                    // 收到的报文队列

        // 数据包接收Event函数，由用户自己定义
        // response of cmd.
        public delegate void ProcessPacketDelegate(baseReceivedPacket pk);
        public static event ProcessPacketDelegate EvProcessReceivedPacket;
        private static object locker = new object();

        // Static 构造函数
        static MagneticOriginalPacket()
        {
            pkqueue = new Queue<baseReceivedPacket>(); // 创建报文队列
            Thread pkproc = new Thread(PacketThread);  // 报文处理线程
            pkproc.Start();
        }

        private static void PacketThread()
        {
            baseReceivedPacket pk;
            while (true)
            {
                autoEvent.WaitOne();              // 阻止线程.可降低CPU占有率，提高性能
                while (pkqueue.Count > 0)
                {
                    lock (locker)
                    {
                        pk = pkqueue.Dequeue();
                    }
                    NotifyEventReceivedPacket(pk);

                }

            }
        }

        // Notify function.
        private static void NotifyEventReceivedPacket(baseReceivedPacket pk)    // 产生数据到达事件
        {
            if (EvProcessReceivedPacket != null)
                EvProcessReceivedPacket(pk);                         // 调用事件处理
        }

        public static byte[] BuildOriginalPacket(byte[] dataBuffer, ushort cmd) // 对DATA应用数据进行头、尾封装
        {
            byte fcs = 0;
            byte[] buffer = new byte[dataBuffer.Length + (int)PacketFieldLen.FIXLEN];  // 需要将SOF,LEN,CMD,FCS加进去
            for (int i = 0; i < dataBuffer.Length; i++)
                buffer[(int)PacketFieldPos.DATA0 + i] = dataBuffer[i];
            // 封装头
            buffer[(int)PacketFieldPos.SOF] = (byte)PacketField.SOF;
            buffer[(int)PacketFieldPos.LEN] = (byte)dataBuffer.Length;
            buffer[(int)PacketFieldPos.CMD0] = (byte)cmd;
            buffer[(int)PacketFieldPos.CMD1] = (byte)(cmd>>8);
            
            // 封装尾
            for (int i = (int)PacketFieldPos.LEN; i < dataBuffer.Length + (int)PacketFieldPos.DATA0; i++)
                fcs ^= buffer[i];
            buffer[(int)PacketFieldPos.FCS + dataBuffer.Length] = fcs;
            return buffer;
        }
        
        public static void PacketParse(object sender, List<byte> rxPacket)
        { // 数据格式类似: -234,263,-271\n
            int FisrtCommaIndex, SecondCommaIndex, NewLineIndex;
            int numb1,numb2,numb3;
            char[] s;
            string str;
            while (rxPacket.Count > 3) // 2个逗号，一个'\n'，共至少3个字符
            {
                FisrtCommaIndex = rxPacket.IndexOf((byte)(','));// 找到第一个逗号，返回所在的位置
                if (FisrtCommaIndex == -1)
                {
                    rxPacket.Clear();        // 如果没有找到一个逗号或者逗号在第一个位置,则清空数据
                    break;
                }
                else if (FisrtCommaIndex == 0)
                {
                    rxPacket.RemoveRange(0, 1); // 如果逗号排在第一个位置，则去除第一个字符，然后重新回到循环
                }
                else if (FisrtCommaIndex == rxPacket.Count - 1)
                {
                    // 如果逗号处于最后一个字符，则说明数据还不够多需要继续积攒字节数，重新进入循环
                }
                else
                {
                    s = new char[FisrtCommaIndex];
                    for (int i = 0; i < FisrtCommaIndex; i++)
                        s[i] = (char)rxPacket[i];
                    str = new String(s);
                    if (Int32.TryParse(str, out numb1))
                    {
                        SecondCommaIndex = rxPacket.IndexOf((byte)(','), FisrtCommaIndex + 1); // 寻找第二个逗号
                        NewLineIndex = rxPacket.IndexOf((byte)('\n'), FisrtCommaIndex + 1); // 寻找换行符号
                        if (SecondCommaIndex == -1 || NewLineIndex == -1)
                        {
                            // 重新进入循环继续执行..等待数据继续积攒
                        }
                        else
                        {
                            if (NewLineIndex < SecondCommaIndex)
                            {// 说明回车符在第二个逗号之前，这时说明第一个逗号位置不对，去掉换行符及之前的字节，然后重新开始循环
                                rxPacket.RemoveRange(0, NewLineIndex + 1); //去掉换行符之前的数据
                            }
                            else
                            {
                                // 获取第2个数据
                                s = new char[SecondCommaIndex - FisrtCommaIndex-1];
                                for(int i=0; i<SecondCommaIndex - FisrtCommaIndex-1; i++)
                                    s[i] = (char)rxPacket[FisrtCommaIndex+1+i];
                                str = new String(s);
                                if (Int32.TryParse(str, out numb2))
                                {
                                    // 获取第3个数据
                                    s = new char[NewLineIndex - SecondCommaIndex - 1];
                                    for (int i = 0; i < NewLineIndex - SecondCommaIndex - 1; i++)
                                        s[i] = (char)rxPacket[SecondCommaIndex + 1 + i];
                                    str = new String(s);
                                    if (Int32.TryParse(str, out numb3))
                                    {
                                        baseReceivedPacket rsp = (baseReceivedPacket)PacketClassDictionary.CreateInstanse(MagneticReport.type); // 根据类型创建报文实例
                                        (rsp as MagneticReport).numb1 = numb1;
                                        (rsp as MagneticReport).numb2 = numb2;
                                        (rsp as MagneticReport).numb3 = numb3;
                                        lock (locker)
                                        {
                                            pkqueue.Enqueue(rsp);
                                        }
                                        autoEvent.Set();
                                    }
                                    rxPacket.RemoveRange(0, NewLineIndex + 1); //去掉换行符之前的数据
                                }
                                else
                                {
                                    rxPacket.RemoveRange(0, SecondCommaIndex + 1);    // 移除第二个"，"以及之前所有数据。然后重新进入循环
                                }
                            }
                            
                        }
                    }
                    else
                    {//　 
                        rxPacket.RemoveRange(0, FisrtCommaIndex + 1);    // 移除第一个"，"以及之前所有数据。然后重新进入循环
                    }
                }
 
 
            }//while 
        }
    }
}
